package com.aisile.admin.service.impl;

import com.aisile.admin.AdminApplication;
import com.aisile.admin.mapper.AdChannelMapper;
import com.aisile.admin.service.AdChannelService;
import com.aisile.model.admin.dtos.ChannelDto;
import com.aisile.model.admin.pojos.AdChannel;
import com.aisile.model.common.dtos.PageResponseResult;
import com.aisile.model.common.dtos.ResponseResult;
import com.aisile.model.common.enums.AppHttpCodeEnum;
import com.aisile.utils.threadlocal.AdminThreadLocalUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.swagger.models.auth.In;
import org.apache.commons.lang3.StringUtils;

import org.apache.directory.api.util.exception.Exceptions;
import org.apache.kafka.common.protocol.types.Field;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.web.bind.annotation.*;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.management.MemoryUsage;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.SimpleTimeZone;
import java.util.concurrent.*;
import java.util.logging.Handler;

@CrossOrigin
@Service
public class AdChannelServiceImpl extends ServiceImpl<AdChannelMapper,AdChannel> implements AdChannelService {
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private AdChannelMapper adChannelMapper;


    @Override
    public ResponseResult findByNameAndPage(ChannelDto dto) {
//无脑判断

//        条件
        return null;

    }



    @Override
    public ResponseResult findListByPage(ChannelDto dto) {
        return null;
    }

    @Override
    public ResponseResult saveAdChannel(@RequestBody AdChannel adChannel) {
        // 双重校验  前端校验一遍  后端校验一遍
        // 如果是|| 从左向右判断 依次判断  true之后继续判断
        // 如果是&& 要看所有条件执行情况
        if (adChannel == null || adChannel.getName() == null || StringUtils.isBlank(adChannel.getName())) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        // 接口幂等性 数据重复 重复请求，返回的值是一样的 就是幂等 返回的值不一样 就是不幂等
        // 当请求是否可以改变服务器端数据 能改变 就不安全  不能改变就是安全
        // get请求 天然幂等且安全  post请求 不幂等且不安全  put请求 幂等且不安全  delete请求 幂等且不安全
        // 所谓的线程安全是什么？ 当多线程访问同一数据源（除redis以外）就是线程不安全
        // 频道添加会不会添加重复的数据？ 如果不想让数据重复添加  有几种方式？
        // 1. 业务上 先查后插方式 配合 数据库锁或者分布式锁
        // 2. 数据库中 添加唯一约束（后端代码）
        int i = this.count(Wrappers.<AdChannel>lambdaQuery().eq(
                AdChannel::getName, adChannel.getName()
        ));
        if (i > 0) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        // 可以添加了
        // 需要自维护创建时间
        adChannel.setCreatedTime(new Date());
        this.save(adChannel);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult updateAdChannel( AdChannel adChannel) {
        //1.参数检查
        if(adChannel == null || adChannel.getId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //2.修改
        updateById(adChannel);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }



    @Override
    public ResponseResult getPageList(ChannelDto dto) {
              if(dto==null){
                  return ResponseResult.errorResult(AppHttpCodeEnum.PATH_ERROR);
              }
              dto.checkParam();
        LambdaQueryWrapper<AdChannel> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(!StringUtils.isEmpty(dto.getName()),AdChannel::getName,dto.getName());
        Page<AdChannel> page = new Page<>(dto.getPage(), dto.getSize());
        IPage<AdChannel> ipage = this.baseMapper.selectPage(page, wrapper);
        ResponseResult responseResult = new PageResponseResult(dto.getPage(), dto.getSize(), Integer.valueOf(ipage.getTotal() + ""));
        responseResult.setData(ipage.getRecords());
        return responseResult;

    }

    @Override
    public ResponseResult deleteId(int id) {
        this.removeById(id);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult updateStatusy(int id, boolean status) {
        AdChannel adChannel = this.getById(id);
        adChannel.setStatus(status);
        this.updateById(adChannel);

        return ResponseResult.okResult(2000,"修改成功");
    }

    @Override
    public ResponseResult updateStatuso(int id, Boolean status) {
        AdChannel byId = this.getById(id);
        byId.setStatus(status);
        if(status==null){
            return ResponseResult.okResult(2001,"该值不能为空");
        }
        this.updateById(byId);
        return ResponseResult.okResult(2000,"修改成功");
    }

    @Override
    public ResponseResult updateyStatusy(int id, Boolean status) {
        AdChannel byId = this.getById(id);
        byId.setStatus(status);
        if(status==null){
            return ResponseResult.okResult(2001,"该值不能为空");
        }
        this.updateById(byId);
        return ResponseResult.okResult(2000,"修改成功");
    }



    @Override
    public ResponseResult daoChu2() {
        return null;
    }

    @Override
    public ResponseResult daoChu(AdChannel adChannel) {
//        if (adChannel==null ||adChannel.getName()==null ||"".equals(adChannel.getName())){
//            return ResponseResult.okResult(2001,"缺少参数!");
//        }
//        // 创建一个线程池
//        ExecutorService executorService = Executors.newFixedThreadPool(5);
//        // 模拟需要导出的数据列表
//        List<AdChannel> dataList = new ArrayList<>();
//        // ... 填充数据列表 ...
//        // 创建一个CompletionService，用于存储线程执行结果
//        CompletionService<ExportResult> completionService = new ExecutorCompletionService<>(executorService);
//        // 提交导出任务
//        for (AdChannel data : dataList) {
//            completionService.submit(() -> exportData(data));
//        }
//        // 获取导出结果
//        for (int i = 0; i < dataList.size(); i++) {
//            try {
//                Future<ExportResult> future = completionService.take();
//                ExportResult result = future.get();
//                if (result.isSuccess()) {
//                    System.out.println("数据导出成功：" + result.getData());
//                } else {
//                    System.out.println("数据导出失败：" + result.getErrorMessage());
//                }
//            } catch (InterruptedException | ExecutionException e) {
//                e.printStackTrace();
//            }
        return null;
        }

    @Override
    public ResponseResult exportData() {
        List<AdChannel> adChannels = adChannelMapper.selectList(null);
        Thread thread = new Thread(() -> {
            this.execute(adChannels);
        });
        thread.start();
        return ResponseResult.okResult(0,"导出已经开始了");
    }

    private void execute(List<AdChannel> adChannels) {
        String fileName="AdChannels_"+ LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss"))+".xlsx";
        String filePath="D:/img/"+fileName;
        XSSFWorkbook workbook = new XSSFWorkbook();
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(filePath);
            Sheet sheet = workbook.createSheet("AdChannels");
            //创建行
            Row row = sheet.createRow(0);
              row.createCell(0).setCellValue("ID");
              row.createCell(1).setCellValue("频道名称");
              row.createCell(2).setCellValue("频道描述");
              row.createCell(3).setCellValue("是否默认频道");
              row.createCell(4).setCellValue("状态");
              row.createCell(5).setCellValue("默认排序");
              row.createCell(6).setCellValue("创建时间");
              if(adChannels!=null){
                   int rowNum=1;
                  for (AdChannel adChannel : adChannels) {
                      if(adChannel!=null){
                          Row row1 = sheet.createRow(rowNum++);
                          row1.createCell(0).setCellValue(adChannel.getId());
                          row1.createCell(1).setCellValue(adChannel.getName());
                          row1.createCell(2).setCellValue(adChannel.getDescription());
                          row1.createCell(3).setCellValue(adChannel.getIsDefault());
                          row1.createCell(4).setCellValue(adChannel.getStatus());
                          row1.createCell(5).setCellValue(adChannel.getOrd());
                          row1.createCell(6).setCellValue(new SimpleDateFormat("yyyy-MM-dd").format(adChannel.getCreatedTime()));
                      }
                  }

              }
              workbook.write(fileOutputStream);
              redisTemplate.opsForValue().set("admin+",new Date()+"",5*10,TimeUnit.MINUTES);
        } catch (FileNotFoundException e) {
            System.err.println("导出的AdChannel到Excel文件时发送异常错误："+e.getMessage());
        } catch (IOException e) {
            System.out.println("导出的Excel文件路径："+filePath);
        }


    }


    @Override
    public ResponseResult checkExportResultInRedis() {
//        从主线程中找出admin+如果没有就是未完成
        Object result = redisTemplate.opsForValue().get("admin+");
        if(result!=null){
              return ResponseResult.okResult(result.toString());
        }
        return ResponseResult.errorResult(5000,"导出完成");
    }


}
